﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using System.Xml.Serialization;
using System.IO;

namespace intelliEssay.Core.DocumentStructure
{
    /// <summary>
    /// Represents a standard format
    /// </summary>
    public static class StandardFormats
    {
        /// <summary>
        /// Gets the standarad format for a specific part of the document.
        /// </summary>
        /// <param name="documentpart">the part whose standarad format is requested</param>
        /// <param name="levelIndex">This parameter is used in a array structure of the document, for example, if documentpart is
        /// LviParagraph, LevelIndex is 1, then standard format of the level 1 title is returned. If the documentpart specified
        /// is not an array,this parameter is ignored</param>
        /// <returns></returns>
        public static Paragraph GetStandardFormatByDocumentPart(DocumentParts documentpart, int levelIndex, Task tsk)
        {
            //  string path = @"standardformat.docx";
            string queryString = documentpart.ToString();
            switch (documentpart)
            {
                case DocumentParts.Acknowledgement:
                case DocumentParts.AcknowledgementContent:
                    return Undefined;
            }
            if (documentpart.ToString() == "LviParagraph")
            {
                queryString += levelIndex;
            }
            WordprocessingDocument wd = tsk.taskSetting.standardDocument;
            Paragraph result = wd.MainDocumentPart.Document.Body.Elements<Paragraph>().FirstOrDefault<Paragraph>(o =>
                {
                    var attributes = o.GetAttributes();
                    return attributes.Any<OpenXmlAttribute>(x =>
                        {
                            return x.LocalName == "documentPart" && x.Value.ToLowerInvariant() == queryString.ToLowerInvariant();
                        });
                });

            if (result == null)
            {
                if (documentpart.ToString() == "LviParagraph")
                {
                    result = wd.MainDocumentPart.Document.Body.Elements<Paragraph>().FirstOrDefault(o =>
                        {
                            return o.GetAttributes().Any<OpenXmlAttribute>(x =>
                                {
                                    return x.LocalName == "documentPart" && x.Value.ToLowerInvariant() == "lviparagraph#default";
                                });
                        });
                }
            }
            if (result == null)
            {
                return Undefined;
            }
            return result;
        }
        // private static Dictionary<DocumentParts, Paragraph> FormatDictionary = new Dictionary<DocumentParts, Paragraph>();
        private static Paragraph _Undefined = new Paragraph()
        {
            ParagraphProperties = new ParagraphProperties()
            {
                Indentation = new Indentation()
                {
                    Left = "0",
                    Right = "0"
                },
                Justification = new Justification()
                {
                    Val = JustificationValues.Left
                }
            }
        };
        private static Run _DefaultRun = new Run()
        {
            RunProperties = new RunProperties()

        };
        /// <summary>
        /// This property is used when standard format is not defined for certain format.
        /// This property returns a paragraph whose rpr and ppr with common properties set
        /// </summary>
        public static Paragraph Undefined
        {
            get
            {
                System.Threading.Monitor.Enter(_Undefined);
                if (_Undefined.ChildElements == null)
                {
                    _Undefined.AppendChild<Run>(_DefaultRun);
                }
                System.Threading.Monitor.Exit(_Undefined);
                return _Undefined;
            }
        }
    }
}
